#include "../src/parser/sql_parser.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

// Test helper functions
static void print_test_header(const char* test_name);
static void print_test_result(const char* test_name, bool passed);

static void print_test_header(const char* test_name) {
    printf("\n=== %s ===\n", test_name);
}

static void print_test_result(const char* test_name, bool passed) {
    printf("%s: %s\n", test_name, passed ? "PASSED" : "FAILED");
}

// Test GROUP BY parsing
static bool test_group_by_parsing(void) {
    print_test_header("Testing GROUP BY Parsing");
    
    const char* sql = "SELECT name, COUNT(*) FROM users GROUP BY name";
    printf("Parsing SQL: %s\n", sql);
    
    parser_t* parser = parser_create(sql);
    if (!parser) {
        printf("Failed to create parser\n");
        return false;
    }
    
    statement_t* stmt = parser_parse_statement(parser);
    bool success = false;
    
    if (parser_has_error(parser)) {
        printf("Parser error: %s\n", parser_get_error(parser));
    } else if (stmt && stmt->type == STMT_SELECT) {
        printf("Successfully parsed SELECT with GROUP BY\n");
        
        if (stmt->data.select.group_by) {
            printf("GROUP BY clause found\n");
            success = true;
        } else {
            printf("GROUP BY clause not found in statement\n");
        }
        
        statement_destroy(stmt);
    } else {
        printf("Failed to parse statement or wrong statement type\n");
    }
    
    parser_destroy(parser);
    return success;
}

// Test HAVING parsing
static bool test_having_parsing(void) {
    print_test_header("Testing HAVING Parsing");
    
    const char* sql = "SELECT name, COUNT(*) FROM users GROUP BY name HAVING COUNT(*) > 1";
    printf("Parsing SQL: %s\n", sql);
    
    parser_t* parser = parser_create(sql);
    if (!parser) {
        printf("Failed to create parser\n");
        return false;
    }
    
    statement_t* stmt = parser_parse_statement(parser);
    bool success = false;
    
    if (parser_has_error(parser)) {
        printf("Parser error: %s\n", parser_get_error(parser));
    } else if (stmt && stmt->type == STMT_SELECT) {
        printf("Successfully parsed SELECT with GROUP BY and HAVING\n");
        
        if (stmt->data.select.group_by && stmt->data.select.having) {
            printf("Both GROUP BY and HAVING clauses found\n");
            success = true;
        } else {
            printf("GROUP BY: %s, HAVING: %s\n", 
                   stmt->data.select.group_by ? "found" : "not found",
                   stmt->data.select.having ? "found" : "not found");
        }
        
        statement_destroy(stmt);
    } else {
        printf("Failed to parse statement or wrong statement type\n");
    }
    
    parser_destroy(parser);
    return success;
}

// Test HAVING without GROUP BY (should fail)
static bool test_having_without_group_by(void) {
    print_test_header("Testing HAVING without GROUP BY (should fail)");
    
    const char* sql = "SELECT name FROM users HAVING COUNT(*) > 1";
    printf("Parsing SQL: %s\n", sql);
    
    parser_t* parser = parser_create(sql);
    if (!parser) {
        printf("Failed to create parser\n");
        return false;
    }
    
    statement_t* stmt = parser_parse_statement(parser);
    bool success = false;
    
    if (parser_has_error(parser)) {
        printf("Expected parser error: %s\n", parser_get_error(parser));
        success = true;  // This should fail, so error is expected
    } else if (stmt) {
        printf("Unexpected success - HAVING without GROUP BY should fail\n");
        statement_destroy(stmt);
    }
    
    parser_destroy(parser);
    return success;
}

// Test complex GROUP BY with multiple columns
static bool test_complex_group_by(void) {
    print_test_header("Testing Complex GROUP BY with Multiple Columns");
    
    const char* sql = "SELECT department, position, COUNT(*) FROM employees GROUP BY department, position";
    printf("Parsing SQL: %s\n", sql);
    
    parser_t* parser = parser_create(sql);
    if (!parser) {
        printf("Failed to create parser\n");
        return false;
    }
    
    statement_t* stmt = parser_parse_statement(parser);
    bool success = false;
    
    if (parser_has_error(parser)) {
        printf("Parser error: %s\n", parser_get_error(parser));
    } else if (stmt && stmt->type == STMT_SELECT) {
        printf("Successfully parsed SELECT with complex GROUP BY\n");
        
        if (stmt->data.select.group_by) {
            printf("Complex GROUP BY clause found\n");
            success = true;
        } else {
            printf("GROUP BY clause not found in statement\n");
        }
        
        statement_destroy(stmt);
    } else {
        printf("Failed to parse statement or wrong statement type\n");
    }
    
    parser_destroy(parser);
    return success;
}

// Test complete query with all clauses
static bool test_complete_query(void) {
    print_test_header("Testing Complete Query with All Clauses");
    
    const char* sql = "SELECT department, AVG(salary) FROM employees WHERE age > 25 GROUP BY department HAVING AVG(salary) > 50000 ORDER BY department";
    printf("Parsing SQL: %s\n", sql);
    
    parser_t* parser = parser_create(sql);
    if (!parser) {
        printf("Failed to create parser\n");
        return false;
    }
    
    statement_t* stmt = parser_parse_statement(parser);
    bool success = false;
    
    if (parser_has_error(parser)) {
        printf("Parser error: %s\n", parser_get_error(parser));
    } else if (stmt && stmt->type == STMT_SELECT) {
        printf("Successfully parsed complete SELECT statement\n");
        
        bool has_select = stmt->data.select.select_list != NULL;
        bool has_from = stmt->data.select.from_list != NULL;
        bool has_where = stmt->data.select.where_clause != NULL;
        bool has_group_by = stmt->data.select.group_by != NULL;
        bool has_having = stmt->data.select.having != NULL;
        bool has_order_by = stmt->data.select.order_by != NULL;
        
        printf("Clauses found:\n");
        printf("  SELECT: %s\n", has_select ? "yes" : "no");
        printf("  FROM: %s\n", has_from ? "yes" : "no");
        printf("  WHERE: %s\n", has_where ? "yes" : "no");
        printf("  GROUP BY: %s\n", has_group_by ? "yes" : "no");
        printf("  HAVING: %s\n", has_having ? "yes" : "no");
        printf("  ORDER BY: %s\n", has_order_by ? "yes" : "no");
        
        success = has_select && has_from && has_where && has_group_by && has_having && has_order_by;
        
        statement_destroy(stmt);
    } else {
        printf("Failed to parse statement or wrong statement type\n");
    }
    
    parser_destroy(parser);
    return success;
}

int main() {
    printf("GROUP BY and HAVING Test Suite\n");
    printf("==============================\n");
    
    int passed = 0;
    int total = 0;
    
    // Run all tests
    struct {
        const char* name;
        bool (*test_func)(void);
    } tests[] = {
        {"GROUP BY Parsing", test_group_by_parsing},
        {"HAVING Parsing", test_having_parsing},
        {"HAVING without GROUP BY", test_having_without_group_by},
        {"Complex GROUP BY", test_complex_group_by},
        {"Complete Query", test_complete_query},
        {NULL, NULL}
    };
    
    for (int i = 0; tests[i].name != NULL; i++) {
        total++;
        bool result = tests[i].test_func();
        if (result) {
            passed++;
        }
        print_test_result(tests[i].name, result);
    }
    
    printf("\n=== Test Summary ===\n");
    printf("Passed: %d/%d\n", passed, total);
    printf("Success rate: %.1f%%\n", (double)passed / total * 100.0);
    
    return (passed == total) ? 0 : 1;
}